package fr.cephb.locustree.svg;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class DefaultPacker
	implements Packer
	{
	private int featureHeight=12;
	private int min_distance=2;
	public DefaultPacker()
		{
		
		}
	
	public int getMinDistance()
		{
		return this.min_distance;
		}
	
	public void setMinDistance(int min_distance)
		{
		this.min_distance = min_distance;
		}
	
	
	protected boolean overlap(final Rectangle o1,final Rectangle o2)
		{
		if(o1.x>o2.x)
			{
			return overlap(o2, o1);
			}
		
		int R1= o1.x+o1.width;
		int L2= o2.x;
		return (R1+getMinDistance() >= L2);
		}
	
	@Override
	public void setEntityHeight(int featureHeight)
		{
		this.featureHeight = Math.max(1,featureHeight);
		}
	
	public int getEntityHeight()
		{
		return this.featureHeight;
		}
	
	public int getMaxLines()
		{
		return 30;
		}
	@Override
	public void pack(List<MappedXY> mapped_objects)
		{
		List<List<MappedXY>> lines= new ArrayList<List<MappedXY>>();
		for(MappedXY entity:mapped_objects)
			{
			Rectangle bounds= entity.getBounds();
			bounds.height= getEntityHeight();
			int y,x;
			for(y=0;y<lines.size();++y)
				{
				List<MappedXY> mappeds= lines.get(y);
				for(x=0;x< mappeds.size();++x)
					{
					if(overlap(mappeds.get(x).getBounds(),bounds)) break;
					}
				if(x==mappeds.size())
					{
					bounds.y= y*getEntityHeight();
					mappeds.add(entity);
					break;
					}
				}
			if(y==lines.size())
				{
				List<MappedXY> line=new ArrayList<MappedXY>();
				bounds.y=lines.size()*getEntityHeight();
				line.add(entity);
				lines.add(line);
				
				}
			}
		if(lines.size()> getMaxLines()) reduce(lines);
		}
	/* called when there are too many rows */
	public void reduce(List<List<MappedXY>> lines)
		{
		if(getMaxLines()<=1) return;
		Random rand =new Random(1L);//use always the same seed;
		for(List<MappedXY> line:lines)
			{
			for(MappedXY xy:line) xy.setLabelFlag(MappedXY.LABEL_IGNORED);
			}
		while(lines.size()> getMaxLines())
			{
			List<MappedXY> last=lines.remove(lines.size()-1);
			for(MappedXY xy:last)
				{
				xy.getBounds().y=rand.nextInt(getMaxLines())*getEntityHeight();
				}
			}
		}
	}
